#include "options_philadelphia.h"

/* inicializace static polozek */

int PhiladelphiaOptions::problemInstance_[9][2] = {
	{0, 0}, {0, 1}, {1, 0}, {1, 1}, {2, 0}, {2, 1}, {3, 0}, {0, 2}, {4, 0}
};
int PhiladelphiaOptions::demandVectors_[5][21] = {
	{ 8,25,8,8,8,15,18,52,77,28,13,15,31,15,36,57,28,8,10,13,8 },
	{ 5,5,5,8,12,25,30,25,30,40,40,45,20,30,25,15,15,30,20,20,25 },
	{ 20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20 },
	{ 16,50,16,16,16,30,36,104,154,56,26,30,62,30,72,114,56,16,20,26,16 },
	{ 32,100,32,32,32,60,72,208,308,112,52,60,124,60,144,228,112,32,40,52,32 }
};
double PhiladelphiaOptions::reuseDistances_[3][6] = {
	{ 4 * ODM3PUL, 2 * ODM3PUL, 1, 1, 1, 0 },
	{ ODM7, 2 * ODM3PUL, 1, 1, 1, 0 },
	{ 4 * ODM3PUL, 2, 1, 1, 1, 0 },
};

/** Nacte znamou instanci.
 * \param d cislo instance
 */
void PhiladelphiaOptions::LoadProblem(int d) {
	if ((1 <= d) && (d <= 9)) {
		demands = demandVectors_[problemInstance_[d - 1][0]];
		reuse = reuseDistances_[problemInstance_[d - 1][1]];
		detail = d;
	}
	else {
		Log() << "!Neznamy problem Philadelphie. Znam jen 1 - 9!" << std::endl;
	}
}

/** Nacte nastaveni z daneho XML elementu.
 * \param settings nastaveni Philadelphie
 */
void PhiladelphiaOptions::Read(ticpp::Element * settings) {
	bool error = false;
	settings->GetAttributeOrDefault("instance", &problem, 0);
	if (problem != 0) {
		LoadProblem(problem);
	}
	else {
		// read demands
		ticpp::Element * demandElem = settings->FirstChildElement("demands", false);
		if (!demands) {
			error = true;
		}
		else {
			std::istringstream demandValues(demandElem->GetText(false));
			int d, i = 0;
			demands = new int[21];
			demands_delete = true;
			while (demandValues >> d && i < 21) {
				demands[i++] = d;
			}
			if (i != 21) {
				error = true;
			}
		}
		if (!error) {
			// read reuse distances
			ticpp::Element * reuseElem = settings->FirstChildElement("reuse", false);
			if (!reuseElem) {
				reuse = reuseDistances_[0];
			}
			else {
				std::istringstream reuseValues(reuseElem->GetText(false));
				std::list<double> reuseDistances;
				double d;
				while (reuseValues >> d) {
					reuseDistances.push_back(d);
				}
				reuse_delete = true;
				reuse = new double[reuseDistances.size()];
				reuse_size = reuseDistances.size();
				int count = 0;
				for (std::list<double>::const_iterator i = reuseDistances.begin(); i != reuseDistances.end(); ++i) {
					reuse[count++] = *i;
				}
			}
		}
	}
	if (error) {
		if (demands_delete) {
			delete[] demands;
			demands_delete = false;
		}
		problem = 1;
		LoadProblem(problem);
	}
}

/** Vypise do logu nastaveni Philadelphie.
 */
void PhiladelphiaOptions::Print() {
	Log() << "Nastaveni Philadelphie: " << std::endl << " - pozadavky: ";
	for (int i = 0; i < 21; ++i) {
		Log() << demands[i] << ' ';
	}
	Log() << std::endl << " - pouzitelne vzdalenosti: ";
	for (int i = 0; i < reuse_size; ++i) {
		Log() << reuse[i] << ' ';
	}
	Log() << std::endl;
}
